package com.goldsprite.gdxcore.entities;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.utils.*;
import com.goldsprite.gdxcore.utils.*;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.scenes.scene2d.ui.Widget;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.goldsprite.utils.math.Vector2;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;

public class GameWorld extends Widget{
	private final Array<IRenderable> entities = new Array<>();
	private GameWorldGroup worldGroup;
	private float delta;
	public OrthographicCamera worldCam, transCam;
	private Vector2 worldSize = new Vector2();

	private boolean[] isUIEvent = {false};
	private OrthoCamController cameraController;

	public float worldWidth = 1920, worldHeight = 1080;
	public float worldRatio = worldWidth/worldHeight;
	public FrameBuffer fbuf;
	public Texture bufTex;
	public TextureRegion bufRegion;
	public SpriteBatch bufBatch;
	//debug绘制
	private ShapeRenderer sBatch;
	private Texture blackBackground;

	public float screenWidthRatio, editorWidth, editorHeight;
	
	public static boolean enableDebugGizmos = true;

	public void init(){
		screenWidthRatio = 1f * Gdx.graphics.getWidth() / Gdx.graphics.getHeight();
		editorWidth = 960f * 1f;
		editorHeight = editorWidth / screenWidthRatio;

		worldWidth = 1920f/2;
		worldHeight = 1080f/2;
		init(worldWidth, worldHeight);
	}
	public void init(float worldWidth, float worldHeight){
		blackBackground = ColorTextureUtils.createColorTexture(Color.BLACK);

		worldCam = new OrthographicCamera();
		transCam = new OrthographicCamera();
		cameraController = new OrthoCamController(transCam, isUIEvent);
		worldGroup.getScreen().getImp().addProcessor(cameraController);

		fbuf = new FrameBuffer(Pixmap.Format.RGBA8888, (int)worldWidth*2, (int)worldHeight*2, false);
		bufTex = fbuf.getColorBufferTexture();
		bufRegion = new TextureRegion(bufTex);
		bufRegion.flip(false, true);
		
		bufBatch = new SpriteBatch();
		sBatch = new ShapeRenderer();
	}

	public void addEntity(IRenderable entity) {
		entities.add(entity);
		entity.setWorld(this);
	}

	public void removeEntity(IRenderable entity) {
		entities.removeValue(entity, true);
	}


	@Override
	public void act(float delta) {
		super.act(delta);
		//uiGroup.act(delta);

		this.delta = delta;
		updateWorldCamera();
		// 渲染到 FrameBuffer
		{
			Viewport viewport = getWorldGroup().screen.getViewport();
			fbuf.begin();
			ScreenUtils.clear(0, 0, 0, 0);
			drawFBuf(bufBatch);
			if(enableDebugGizmos) drawFBufGizmos(sBatch);
			fbuf.end();  // 渲染结束
			viewport.apply(true);
		}
	}

	private void drawFBuf(SpriteBatch bufBatch) {
		bufBatch.setProjectionMatrix(worldCam.combined);
		bufBatch.begin();
		for(IRenderable ent : entities){
			ent.act(delta);
			ent.render(bufBatch, delta);
		}
		bufBatch.end();
	}
	private void drawFBufGizmos(ShapeRenderer sBatch){
		Gdx.gl.glLineWidth(2);
		sBatch.setProjectionMatrix(worldCam.combined);
		sBatch.begin(ShapeRenderer.ShapeType.Line);
		for(IRenderable ent : entities){
			ent.renderDebug(sBatch, delta);
		}
		sBatch.end();
	}

	@Override
	public void draw(Batch batch, float parentAlpha) {
		super.draw(batch, parentAlpha);
		//应用到布局
		{
			batch.setProjectionMatrix(getWorldGroup().screen.getCamera().combined);//必须有，被fbuf改了
			float width, height;
			GameWorldGroup layout = getWorldGroup();
			float lw = layout.getWidth(), lh = layout.getHeight();
			width = lh * worldRatio;
			height = lh;
			if(lw < width){
				width = lw;
				height = lw / worldRatio;
			}
			
			batch.draw(blackBackground, 0, 0, width, height);//绘制黑色底色
			batch.draw(bufRegion, 0, 0, width, height);
		}
	}


	public OrthographicCamera getWorldCam(){
		return (OrthographicCamera) getStage().getCamera();
	}

	public Vector2 getWorldSize(){
		return worldSize.set(getWorldGroup().screenCam.viewportWidth, getWorldGroup().screenCam.viewportHeight);
	}

	public void setWorldGroup(GameWorldGroup worldGroup){
		this.worldGroup = worldGroup;
	}
	public GameWorldGroup getWorldGroup(){
		return worldGroup;
	}


	public void updateWorldCamera(){
		float width = worldWidth;
		float height = worldHeight;
		float camX = 0;
		float camY = 0;


		camX += transCam.position.x * 1;
		camY += transCam.position.y * 1;
		worldCam.zoom = transCam.zoom;

		worldCam.viewportWidth = width;
		worldCam.viewportHeight = height;
		worldCam.position.set(camX+width/2, camY+height/2, 0);
		worldCam.update();

		transCam.viewportWidth = worldCam.viewportWidth;
		transCam.viewportHeight = worldCam.viewportHeight;
		//transCam.position.set(worldCam.position);
		transCam.update();
	}

	float[] realViewRec = new float[4];
	public float[] getRealViewRec(){
		return realViewRec;
	}

}
